scrolledwindow: Handle directional cancellation if there is a single scroll direction
authorCarlos Garnacho <carlosg@gnome.org>
Fri, 16 May 2014 16:35:45 +0000 (18:35 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Fri, 23 May 2014 17:54:32 +0000 (19:54 +0200)
A pan gesture is optionally attached if there is only one scrolling direction, the pan
gesture orientation is changed so movements tangential to the scroll direction get
scrolling cancelled (The pan gesture is automatically denied when that happens, and
that state change spreads to the others gestures in the group). If the pan direction
happens in the expected directions, no cancellation happens, and scrolling eventually
takes place.

gtk/gtkscrolledwindow.c

index 65061d4ffc37bc404930c3be9283db45a4cbfd17..e5fe575cf21c213ca88cbe4de5ce461467be6404 100644 (file)
@@ -149,9 +149,13 @@ struct _GtkScrolledWindowPrivate
   gint     min_content_height;
 
   /* Kinetic scrolling */
-  GtkGesture *drag_gesture;
-  GtkGesture *swipe_gesture;
   GtkGesture *long_press_gesture;
+  GtkGesture *swipe_gesture;
+
+  /* These two gestures are mutually exclusive */
+  GtkGesture *drag_gesture;
+  GtkGesture *pan_gesture;
+
   gdouble drag_start_x;
   gdouble drag_start_y;
 
@@ -717,6 +721,30 @@ scrolled_window_long_press_cancelled_cb (GtkScrolledWindow *scrolled_window,
     priv->in_drag = TRUE;
 }
 
+static void
+gtk_scrolled_window_check_attach_pan_gesture (GtkScrolledWindow *sw)
+{
+  GtkScrolledWindowPrivate *priv = sw->priv;
+
+  if (priv->kinetic_scrolling &&
+      ((priv->hscrollbar_visible && !priv->vscrollbar_visible) ||
+       (!priv->hscrollbar_visible && priv->vscrollbar_visible)))
+    {
+      GtkPanOrientation orientation;
+
+      if (priv->hscrollbar_visible)
+        orientation = GTK_PAN_ORIENTATION_HORIZONTAL;
+      else
+        orientation = GTK_PAN_ORIENTATION_VERTICAL;
+
+      gtk_gesture_pan_set_orientation (GTK_GESTURE_PAN (priv->pan_gesture),
+                                       orientation);
+      gtk_gesture_attach (priv->pan_gesture, GTK_PHASE_CAPTURE);
+    }
+  else
+    gtk_gesture_detach (priv->pan_gesture);
+}
+
 static void
 gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
 {
@@ -755,6 +783,10 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
                             G_CALLBACK (scrolled_window_drag_end_cb),
                             scrolled_window);
 
+  priv->pan_gesture = gtk_gesture_pan_new (widget, GTK_PAN_ORIENTATION_VERTICAL);
+  gtk_gesture_group (priv->pan_gesture, priv->drag_gesture);
+  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->pan_gesture), 1);
+
   priv->swipe_gesture = gtk_gesture_swipe_new (widget);
   gtk_gesture_group (priv->swipe_gesture, priv->drag_gesture);
   gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->swipe_gesture), 1);
@@ -1244,6 +1276,7 @@ gtk_scrolled_window_set_kinetic_scrolling (GtkScrolledWindow *scrolled_window,
     return;
 
   priv->kinetic_scrolling = kinetic_scrolling;
+  gtk_scrolled_window_check_attach_pan_gesture (scrolled_window);
 
   if (priv->kinetic_scrolling)
     {
@@ -2289,6 +2322,7 @@ gtk_scrolled_window_size_allocate (GtkWidget     *widget,
     }
 
   _gtk_scrolled_window_allocate_overshoot_window (scrolled_window);
+  gtk_scrolled_window_check_attach_pan_gesture (scrolled_window);
 }
 
 static gboolean